﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using FastReflection;
using System.Reflection;

namespace PerformanceProfiler
{
    public partial class Form1 : Form
    {
        public class Employee
        {
            public string Name { get; set; }

            public DateTime HireDate { get; set; }

            public int? Age { get; set; }
        }

        public Form1()
        {
            InitializeComponent();
        }

        private void FPTPRunButton_Click(object sender, EventArgs e)
        {
            Employee emp = new Employee { Name = "Mike", Age = null, HireDate = DateTime.Now.AddYears(-3) };

            ExecuteFastPropertyGet(FastProperty<Employee, string>.Make(typeof(Employee).GetProperty("Name")), emp, FPTPGetResults);
            ExecuteFastPropertySet(FastProperty<Employee, string>.Make(typeof(Employee).GetProperty("Name")), emp, "James", FPTPSetResults);
        }

        public static void ExecuteFastPropertyGet<T, P>(FastProperty<T, P> property, T item, Control results)
        {
            DateTime start = DateTime.Now;
            for (int i = 0; i < 10000000; i++)
            {
                P value = property.Get(item);
            }
            DateTime end = DateTime.Now;

            results.Text = (end - start).TotalMilliseconds + "ms";
        }

        public static void ExecuteFastPropertySet<T, P>(FastProperty<T, P> property, T item, P value, Control results)
        {
            DateTime start = DateTime.Now;
            for (int i = 0; i < 10000000; i++)
            {
                property.Set(item,value);
            }
            DateTime end = DateTime.Now;

            results.Text = (end - start).TotalMilliseconds + "ms";
        }

        private void FPRunButton_Click(object sender, EventArgs e)
        {
            Employee emp = new Employee { Name = "Mike", Age = null, HireDate = DateTime.Now.AddYears(-3) };

            ExecuteFastPropertyGet(FastProperty<object, object>.Make(typeof(Employee).GetProperty("Name")), emp, FPGetResults);
            ExecuteFastPropertySet(FastProperty<object, object>.Make(typeof(Employee).GetProperty("Name")), emp, "James", FPSetResults);
        }

        public static void ExecuteStandardGet<T>(PropertyInfo property, T instance, Control results)
        {
            DateTime start = DateTime.Now;
            for (int i = 0; i < 10000000; i++)
            {
                object value = property.GetValue(instance, null);
            }
            DateTime end = DateTime.Now;

            results.Text = (end - start).TotalMilliseconds + "ms";
        }

        public static void ExecuteStandardSet<T, P>(PropertyInfo property, T instance, P value, Control results)
        {
            DateTime start = DateTime.Now;
            for (int i = 0; i < 10000000; i++)
            {
                property.SetValue(instance, value, null);
            }
            DateTime end = DateTime.Now;

            results.Text = (end - start).TotalMilliseconds + "ms";
        }

        private void STDRunButton_Click(object sender, EventArgs e)
        {
            Employee emp = new Employee { Name = "Mike", Age = null, HireDate = DateTime.Now.AddYears(-3) };
            var property = typeof(Employee).GetProperty("Name");
            ExecuteStandardGet(property,emp,STGetResults);
            ExecuteStandardSet(property,emp,"James",STSetResults);
        }

        private static void NativeGet(Employee instance, Control results)
        {
            DateTime start = DateTime.Now;
            for (int i = 0; i < 10000000; i++)
            {
                string value = instance.Name;
            }
            DateTime end = DateTime.Now;

            results.Text = (end - start).TotalMilliseconds + "ms";
        }

        private static void NativeSet(Employee instance, string value, Control results)
        {
            DateTime start = DateTime.Now;
            for (int i = 0; i < 10000000; i++)
            {
                instance.Name = value;
            }
            DateTime end = DateTime.Now;

            results.Text = (end - start).TotalMilliseconds + "ms";
        }

        private void NRunButton_Click(object sender, EventArgs e)
        {
            Employee emp = new Employee { Name = "Mike", Age = null, HireDate = DateTime.Now.AddYears(-3) };
            NativeGet(emp, NGetResults);
            NativeSet(emp, "Jason", NSetResults);
        }

        public static void MakeFastProperties(Control results)
        {
            int propertyCount = 0;
            int typeCount = 0;
            DateTime start = DateTime.Now;
            foreach (var type in Assembly.GetAssembly(typeof(Guid)).GetTypes().Where(p => (!p.IsGenericType || !p.IsGenericTypeDefinition)).ToList())
            {
                foreach (var property in type.GetProperties().Where(p => p.GetIndexParameters().Length == 0).ToList())
                {
                    var fp = property.ToFastProperty();

                    propertyCount++;
                }

                typeCount++;
            }
            DateTime end = DateTime.Now;

            results.Text = (end - start).TotalMilliseconds + "ms" + " - " + typeCount + " types - " + propertyCount + " properties.";
        }

        private void MakeRunButton_Click(object sender, EventArgs e)
        {
            MakeFastProperties(MakeTextBox);
        }
    }
}
